<?php

/**
 * 字段操作类
 *
 * @author birdy <freebirdy@foxmail.com>
 * @link http://www.aiyuangong.com
 */
use think\Config;
use think\Cache;

class Fields
{

    /**
     * 解析请求，返回规则字段配置数据
     * @param string $field  表单字段名称
     * @param string $method 请求方式
     * @param array  $not_allow_name 禁止使用的字段
     * @return json
     */
    public static function request($field = 'form', $method = 'post', $not_allow_name = [])
    {
        $not_allow_name = $not_allow_name ?: \think\Db::name('type')->getTableInfo('', 'fields');

        $rule = [
            'title|标题' => 'require|length:2,25',
            'name|名称' => 'require|alphaDash|length:2,30|notin:' . implode(",", $not_allow_name),
            'type|类型' => 'require|in:text,select,radio,textarea,checkbox,password,number,date,datetime,image,time,type,config,table'
        ];

        $message = [
            'title.length' => '标题长度控制在[2-25]字符',
            'name.length' => '名称长度控制在[2-30]字符',
            'name.notin' => '名称不能出现关键词：[' . implode(", ", $not_allow_name) . "]",
            'type.in' => '类型无法识别'
        ];

        $validate = new \think\Validate($rule, $message);

        $rs = $names = [];
        $data = input($method . "." . $field . "/a") ?: [];
        foreach ($data as $k => $v) {
            if (empty($v['name']) && empty($v['title'])) {
                continue;
            }
            if (!$validate->check($v)) {
                return $validate->getError();
            }
            if (in_array($v['name'], $names)) {
                return '字段 ' . $v['name'] . ' 重复';
            }
            $names[] = $v['name'];
            $rule = isset($v['validate']) ? $v['validate'] : [];
            $item = [
                'title' => $v['title'],
                'name' => $v['name'],
                'type' => $v['type'],
                'default' => isset($v['default']) ? $v['default'] : '',
                'option' => isset($v['option']) ? $v['option'] : '',
                'require' => isset($v['require']) ? 1 : 0,
                'validate' => [
                    "datatype" => isset($rule['datatype']) ? $rule['datatype'] : '',
                    "nullmsg" => isset($rule['nullmsg']) ? $rule['nullmsg'] : '',
                    "errormsg" => isset($rule['errormsg']) ? $rule['errormsg'] : '',
                ]
            ];
            $rs[] = $item;
        }
        return $rs;
    }

    /**
     * 获取整个字段树
     * @param string|id $root  表单字段名称
     * @return midxed
     */
    public static function get_tree_data($root = 0, $status = 1, $field = '*', $cache = true)
    {
        $map = ['isdelete' => 0];
        if ($status !== FALSE) {
            $map['status'] = $status ? 1 : 0;
        }

        if ($field != '*') {
            $field .= ',id,name,tag,pid';
            $field = implode(",", array_unique(array_filter(explode(',', $field))));
        }

        $key = false;
        if ($cache) {
            $key = md5("cache_type_all" . serialize($map) . $field);
        }

        $data = cache_read_and_write($key, 'common/common/lists', ['type', $map], 'type');
        if (!$root) {
            return $data;
        }
        if (!is_numeric($root)) {
            $data = reset_by_key(list_to_tree($data), 'tag');
        } else {
            $data = reset_by_key(list_to_tree($data), 'id');
        }

        return isset($data[$root]) ? $data[$root] : 0;
    }

    //根据ＩＤ获取单个结点，自定义字段，已经合并到结点上
    public static function getById($tag, $id = 0)
    {
        if ($tag) {
            $key = 'type_muti_' . $tag . $id;
            $data = Cache::get($key);
            if (!$data) {
                $data = self::get_tree_data($tag);
                $config = json_decode($data['fields'], true) ?: [];
                $config = array_column($config, 'default', 'name');
                $data = self::ulitArraytToSingle($data['_child'], $config);
                if ($id > 0) {
                    if (isset($data[$id])) {
                        if (isset($data[$id]['_child'])) {
                            unset($data[$id]['_child']);
                        }
                        $data = $data[$id];
                    } else if (isset($data['_map'][$id])) {
                        $pkey = $data['_map'][$id];
                        $data = $data[$pkey]["_child"][$id] ?: [];
                    }
                } else {
                    unset($data['_map']);
                }

                Cache::tag('type')->set($key, $data);
            }

            return $data;
        }
        return [];
    }

    private static function ulitArraytToSingle($array, $config, $root = true)
    {
        if (is_array($array)) {
            $array = reset_by_key($array, 'id');
            static $_key_map = [];
            foreach ($array as $k => &$value) {
                $value['fields'] = json_decode($value['fields'], true);
                if (isset($value['_child'])) {
                    $value['_child'] = self::ulitArraytToSingle($value['_child'], $config, false);
                } else {
                    $_key_map[$value['id']] = $value['pid'];
                }

                $value = array_merge($value, $config, $value['fields']);
                unset($value['fields']);
                unset($value['update_time']);
                unset($value['create_time']);
                unset($value['isdelete']);
                unset($value['status']);
            }

            if ($root) {
                $array['_map'] = $_key_map;
            }
            return $array;
        } else {
            return [];
        }
    }

    /**
     * 结点提交数据处理
     * @param type $field
     * @param type $method
     * @param type $not_allow_name
     */
    public static function get_data($fields, $method = 'post', $name = '', $type = '')
    {
        if (!$fields) {
            return [];
        } else if (!is_array($fields)) {
            $fields = json_decode($fields, true);
        }

        $cols = filter_value($fields, "name");
        $name = $name ?: Config::get('fields.field_name');
        $type = $type ?: Config::get('fields.field_type');
        if ($type == 'array') {
            $data = input($method . "." . $name . "/a") ?: [];
            foreach ($data as $k => $v) {
                if (!in_array($k, $cols)) {
                    unset($data[$k]);
                }
            }
        } else {
            $data = [];
            foreach ($cols as $k => $v) {
                $data[$v] = input($method . "." . $name . $v);
                if ($data[$v] === null) {
                    unset($data[$v]);
                }
            }
        }

        //TO DO Validate 需要完善自定义字段的验证

        return $data;
    }

    /**
     * 解析选项字符串为数组格式
     * @param string $option      选项字符串
     * @param string $splitOption 选项分隔符
     * @param string $splitValue  选项值分隔符
     * @return array
     */
    public static function parse_option($option, $splitOption = "", $splitValue = "")
    {
        $splitOption = $splitOption ?: Config::get('fields.split_option');
        $splitValue = $splitValue ?: Config::get('fields.split_value');
        $rs = [];
        $option = explode($splitOption, trim($option)) ?: [];
        $option = array_unique(array_filter($option));
        foreach ($option as $option) {
            $item = explode($splitValue, trim($option));
            if (isset($item[1])) {
                $rs[$item[0]] = $item[1];
            } elseif (isset($item[0])) {
                $item[0] = trim($item[0]);
                $rs[$item[0]] = $item[0];
            }
        }
        return $rs;
    }

    /**
     * ３维数组划分
     * @param string $option      选项字符串
     * @param string $signOption  块标识符
     * @param string $splitOption 选项分隔符
     * @param string $splitValue  选项值分隔符
     * @return array
     */
    public static function parse_option_to_3d($option, $signBlock = '@', $splitOption = "\n", $splitValue = ":")
    {
        $rs = [];
        $option = explode($splitOption, trim($option)) ?: [];
        $option = array_unique(array_filter($option));
        $block = '';
        foreach ($option as $option) {
            $item = explode($splitValue, trim($option));
            if (!$item) {
                continue;
            }
            if (isset($item[1])) {
                if ($item[1] === $signBlock) {
                    $block = $item[0];
                    $rs[$block] = [];
                } else if ($block) {
                    $rs[$block][$item[0]] = $item[1];
                }
            } else {
                $block = $item[0];
                $rs[$block] = [];
            }
        }
        return $rs;
    }

    //清除缓存
    public static function clearCache()
    {
        model("Common/MallCache", "logic")->clearTag('type');
    }

}
